package features.advance.leetcode.array.medium;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;

/**
 *  剑指 Offer 56 - I. 数组中数字出现的次数
 *
 *  难度：中等
 *
 * 一个整型数组 nums 里除两个数字之外，其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n)，空间复杂度是O(1)。
 *
 *
 *
 * 示例 1：
 *
 * 输入：nums = [4,1,4,6]
 * 输出：[1,6] 或 [6,1]
 * 示例 2：
 *
 * 输入：nums = [1,2,10,4,1,4,3,3]
 * 输出：[2,10] 或 [10,2]
 *
 *
 * 限制：
 *
 * 2 <= nums.length <= 10000
 *
 * @author LIN
 * @date 2021-05-31
 */
public class Offer56_1 {

    public static void main(String[] args) {
        Solution solution = new Solution() {
            @Override
            public int[] singleNumbers(int[] nums) {
                // 优化思路：
                Set<Integer> set = new HashSet<>();
                int[] res = new int[2];
                for (int num : nums) {
                    if(set.contains(num)){
                        set.remove(num);

                    }else{
                        set.add(num);
                    }
                    if(set.size() == 2){
                        AtomicInteger i = new AtomicInteger(-1);
                        set.forEach(e->{
                            i.compareAndSet(1,0);
                            res[i.incrementAndGet()] = e;
                        });
                    }
                }
                return res;
            }
        };
        solution = new Solution(){
            @Override
            public int[] singleNumbers(int[] nums) {
                int ret = 0;
                for (int n : nums) {
                    ret ^= n;
                }
                int div = 1;
                while ((div & ret) == 0) {
                    div <<= 1;
                }
                int a = 0, b = 0;
                for (int n : nums) {
                    if ((div & n) != 0) {
                        a ^= n;
                    } else {
                        b ^= n;
                    }
                }
                return new int[]{a, b};
            }
        };
        int[] nums = {1,2,10,4,1,4,3,3};
        int[] ints = solution.singleNumbers(nums);
        System.out.println(Arrays.toString(ints));
    }

    static class Solution {
        public int[] singleNumbers(int[] nums) {
            Set<Integer> set = new HashSet<>();
            for (int num : nums) {
                if(set.contains(num)){
                    set.remove(num);
                }else{
                    set.add(num);
                }
            }
            int[] res = new int[set.size()];
            Object[] objects = set.toArray();
            for (int i = 0; i < objects.length; i++) {
                res[i] = (Integer) objects[i];
            }
            return res;
        }
    }
}
